Skip to content

chore(deps): update ndarray requirement from 0.15 to 0.17#5

Merged
hyperpolymath merged 2 commits into
mainfrom
dependabot/cargo/ndarray-0.17
Dec 16, 2025
Merged

chore(deps): update ndarray requirement from 0.15 to 0.17#5
hyperpolymath merged 2 commits into
mainfrom
dependabot/cargo/ndarray-0.17

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Dec 16, 2025

Copy link
Copy Markdown
Contributor

⚠️ Dependabot is rebasing this PR ⚠️

Rebasing might not happen immediately, so don't worry if this takes some time.

Note: if you make any changes to this PR yourself, they will take precedence over the rebase.


Updates the requirements on ndarray to permit the latest version.

Changelog

Sourced from ndarray's changelog.

Version 0.17.1 (2025-11-02)

Version 0.17.1 provides a patch to fix the originally-unsound implementation of the new array reference types.

The reference types are now all unsized. Practically speaking, this has one major implication: writing functions and traits that accept RawRef and LayoutRef will now need a + ?Sized bound to work ergonomically with ArrayRef. For example, the release notes for 0.17.0 said

Reading / Writing Shape: LayoutRef<A, D>

LayoutRef lets functions view or modify shape/stride information without touching data. This replaces verbose signatures like:

fn alter_view<S>(a: &mut ArrayBase<S, Ix1>)
where S: Data<Elem = f64>;

Use AsRef / AsMut for best compatibility:

fn alter_shape<T>(a: &mut T)
where T: AsMut<LayoutRef<f64>>;

However, these functions now need an additional bound to allow for callers to pass in &ArrayRef types:

fn alter_shape<T>(a: &mut T)
where T: AsMut<LayoutRef<f64>> + ?Sized; // Added bound here

A huge thank you to Sarah Quiñones (@​sarah-quinones) for catching the original unsound bug and helping to fix it. She does truly excellent work with faer-rs; check it out!

Version 0.17.0 (2025-10-14) [YANKED]

Version 0.17.0 introduces a new array reference type — the preferred way to write functions and extension traits in ndarray.
This release is fully backwards-compatible but represents a major usability improvement.
The first section of this changelog explains the change in detail.

It also includes numerous new methods, math functions, and internal improvements — all credited below.

A New Way to Write Functions

TL;DR

ndarray 0.17.0 adds new reference types for writing functions and traits that work seamlessly with owned arrays and views.

When writing functions that accept array arguments:

  • Use &ArrayRef<A, D> to read elements from any array.
  • Use &mut ArrayRef<A, D> to modify elements.
  • Use &T where T: AsRef<LayoutRef<A, D>> to inspect shape/stride only.
  • Use &mut T where T: AsMut<LayoutRef<A, D>> to modify shape/stride only.

All existing function signatures continue to work; these new types are fully opt-in.

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot merge will merge this PR after your CI passes on it
  • @dependabot squash and merge will squash and merge this PR after your CI passes on it
  • @dependabot cancel merge will cancel a previously requested merge and block automerging
  • @dependabot reopen will reopen this PR if it is closed
  • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Updates the requirements on [ndarray](https://github.com/rust-ndarray/ndarray) to permit the latest version.
- [Release notes](https://github.com/rust-ndarray/ndarray/releases)
- [Changelog](https://github.com/rust-ndarray/ndarray/blob/master/RELEASES.md)
- [Commits](rust-ndarray/ndarray@ndarray-rand-0.15.0...0.17.1)

---
updated-dependencies:
- dependency-name: ndarray
  dependency-version: 0.17.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file rust Pull requests that update rust code labels Dec 16, 2025
@hyperpolymath
hyperpolymath merged commit 04415b4 into main Dec 16, 2025
1 of 22 checks passed
@hyperpolymath
hyperpolymath deleted the dependabot/cargo/ndarray-0.17 branch December 16, 2025 13:49
hyperpolymath added a commit that referenced this pull request Jun 4, 2026
## Sub-PR #3 of the Android Kotlin→Rust/Gossamer migration epic

Part of epic **#83**, RFC PR **#97**, tracking sub-issue **#109**. Scope
of #3 is **scaffolding only** — stand up the minimal Gossamer Android
shell so sub-PRs #4#7 can port the actual components. No behaviour
change to existing crates.

### Files added / changed
| File | Change |
|------|--------|
| `android/gossamer.conf.json` | **NEW** — Gossamer app config
(analogous to the former `tauri.conf.json`). Schema
`https://gossamer.dev/schemas/config/v1`, modelled on
`hyperpolymath/panll` + `hyperpolymath/gossamer`. Includes a
`bundle.mobile.android` block (`minSdk 26` / `targetSdk 34`, mirroring
the legacy `AndroidManifest.xml`). |
|
`android/app/src/main/java/ai/neurophone/gossamer/NeurophoneMainActivity.java`
| **NEW** — Java shim extending `io.gossamer.GossamerActivity`;
overrides `getInitialHtml()` to load placeholder HTML in the Gossamer
webview. |
| `crates/neurophone-android/Cargo.toml` | Commented-out `gossamer-rs`
placeholder + TODO (unpublished; see below). |
| `android/app/build.gradle.kts` | Commented-out Gossamer Android
library dependency + TODO. |
| `android/app/src/main/AndroidManifest.xml` | Commented-out
registration of `NeurophoneMainActivity` + TODO (legacy `.MainActivity`
stays LAUNCHER for now). |

Every new file carries `SPDX-License-Identifier: MPL-2.0`.

### `gossamer-rs` resolvability outcome
**Not resolvable in this workspace — left as a commented placeholder, by
design.** Estate precedent (`hyperpolymath/panll`) consumes it only as a
**path dependency to a sibling checkout**: `gossamer-rs = { path =
"../gossamer/bindings/rust" }`. The crate (`gossamer-rs` v0.1.0) is
**not published to crates.io**, and there is no sibling `gossamer`
checkout in neurophone CI. Adding it as a hard dependency would break
`cargo build --workspace`, so per the hard constraint it is commented
out with a TODO(#83 sub-PR #5) documenting the git/path/registry
options. Likewise the **Gossamer Android library**
(`io.gossamer.GossamerActivity`/`GossamerBridge`) ships upstream as a
raw Java source tree + prebuilt `libgossamer.so`, **not** a Maven/AAR
artifact, so the Gradle dependency and the manifest activity
registration are also commented placeholders.

### What I verified
- `cargo metadata --no-deps` → **OK** (all workspace manifests,
including my Cargo.toml edit, parse).
- `cargo build --workspace` → **fails, but with a PRE-EXISTING failure
unrelated to this PR.** The `esn` and `lsm` crates do not compile on
`main` (commit `0a88e45`) due to a `rand` 0.10 / `ndarray-rand` 0.16 API
incompatibility (`no method named random`/`sample`, `RngExt`/`DerefMut`
bounds). This PR touches **zero** compiling Rust: the diff in
`crates/esn`, `crates/lsm`, `crates/neurophone-core` is empty, and the
only Rust change is a **commented** block in
`crates/neurophone-android/Cargo.toml`. **Build/test error delta
introduced by this PR: 0.** `cargo test --workspace` is blocked by the
same pre-existing compile failure, not by anything here.
- No new `gossamer-rs` hard dependency added → CI green-ness is not
regressed by this PR.

> ⚠️ The pre-existing `esn`/`lsm` `rand` breakage on `main` is out of
scope for this scaffolding sub-PR and should be fixed separately.

### `GossamerActivity` API assumptions
Read directly from `hyperpolymath/gossamer`
`android/src/main/java/io/gossamer/GossamerActivity.java`:
- Package `io.gossamer`; subclass and override `getInitialHtml()`
(non-null ⇒ `webView.loadData`) **or** `getInitialUrl()` (used when HTML
is null).
- Parent loads `libgossamer.so` via `System.loadLibrary("gossamer")` in
a static block and registers the `GossamerBridge` JS interface
(`window.GossamerBridge.postMessage(json)`) for native IPC.
- Assumed `gossamer.conf.json` v1 schema is the correct mobile config
surface and that `bundle.mobile.android` is the right place for
SDK/permission config (matches the gossamer reference config; not
independently validated against a live gossamer mobile build, since
Gossamer Android is webview-only today).

### TODOs / risks for sub-PRs #4#8
- **#4**: replace placeholder HTML with the real bundled web UI
(`getInitialUrl()` / `build.frontendDist`); enable the manifest activity
+ move LAUNCHER intent-filter; retire `.MainActivity`.
- **#5**: enable `gossamer-rs` (vendor / git dep / registry) once
resolvable; port the 11 `NativeLib` JNI methods
(init/start/stop/processSensor/queryLocal/queryClaude/query/getNeuralContext/getState/reset/isRunning)
onto the Gossamer IPC bridge, backed by `crates/neurophone-android` +
`crates/neurophone-core`.
- **#6**: port the sensor pipeline (accel/gyro/mag/light/proximity →
LSM→ESN loop).
- **#7**: port `NeurophoneService` (foreground service), `BootReceiver`,
and the home-screen widgets; re-add
`BODY_SENSORS`/`FOREGROUND_SERVICE`/`RECEIVE_BOOT_COMPLETED`/`WAKE_LOCK`
to `gossamer.conf.json`.
- **#8**: remove the legacy `android/` Kotlin tree and drop the
`.hypatia-baseline.json` carve-out once migration lands.
- **Risk**: gossamer Android library distribution mechanism (Maven coord
vs vendored source vs prebuilt `.so` path) is unconfirmed — sub-PR #4/#5
must pick one. Mobile `gossamer.conf.json` fields beyond the desktop
reference are assumed, not validated against a live mobile build.

https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw)_

Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 6, 2026
**Sub-PR #3** of the Android Kotlin→Rust/Gossamer migration epic (#83,
RFC PR #97, tracking sub-issue #109). **Scaffolding only.** No behaviour
change to existing crates; the legacy Kotlin `android/app/` tree is
untouched.

## Files added (all under `android/gossamer/`, all
`SPDX-License-Identifier: MPL-2.0`)

| File | Purpose |
|---|---|
| `gossamer.conf.json` | Gossamer app config (analogous to
`tauri.conf.json`). Schema mirrored from `hyperpolymath/gossamer` and
`hyperpolymath/panll`. Carries identity `ai.neurophone`, the
`bundle.mobile.android` block (minSdk 26 / targetSdk 34 + the permission
set from the legacy `AndroidManifest.xml`), dev/build runner config. |
| `app/src/main/java/ai/neurophone/NeurophoneMainActivity.java` | Java
shim extending `io.gossamer.GossamerActivity`; overrides
`getInitialHtml()` to load placeholder HTML in the Gossamer WebView. |
| `Cargo.toml` | Standalone (non-workspace) scaffold manifest for the
future `neurophone-gossamer` cdylib. `gossamer-rs` dep commented out
(see below). |
| `src/lib.rs` | Inert placeholder lib so the standalone crate compiles;
documents wiring TODOs. |
| `README.adoc` | Documents resolvability, `GossamerActivity` API
assumptions, TODOs/risks for #4#8. |
| `Cargo.lock` | Lock for the standalone scaffold crate (pins
serde/serde_json placeholder deps). |

The `android/**` subtree is exempt from the banned-language CI gate via
`.hypatia-baseline.json` on `main`, so the hand-written Java shim is
acceptable here.

## `gossamer-rs` resolvability outcome

**`gossamer-rs` v0.1.0 is NOT published to crates.io.** In the estate it
is consumed as a **path dependency** from the sibling
`hyperpolymath/gossamer` repo at `bindings/rust` — precedent from
`hyperpolymath/panll`:
```toml
gossamer-rs = { path = "../gossamer/bindings/rust" }
```
That sibling checkout doesn't exist in a neurophone clone, so wiring it
as a hard dependency would break the build. Per the hard constraint (CI
green > "complete" dep), it is **left commented out** with `TODO(#83
sub-PR #8)`. The scaffold manifest is also kept **out of the root
workspace `members`** and carries an empty `[workspace]` table, so
neither `cargo build --workspace` nor `cargo test --workspace` ever
touches it.

## What I verified (build/test)

- `cargo metadata --no-deps` for the root workspace → the 8 existing
crates only; `neurophone-gossamer` is **not** a member. My additions are
inert to the workspace.
- Standalone scaffold: `cargo test --manifest-path
android/gossamer/Cargo.toml` → **compiles + 1 test passes**.
- `cargo build --workspace` / `cargo test --workspace` fail **only** in
`crates/esn` and `crates/lsm` (`ndarray-rand` 0.16 vs `rand` 0.10 API
skew: `random`/`sample`/`random_using`). **This failure pre-exists on
`main`** — reproduced in a pristine `main` worktree (`cargo build -p
esn` exits 101 on `0a88e45`). My PR neither introduces nor worsens it.
⚠️ Pre-existing red workspace flagged below.

## `GossamerActivity` API assumptions (read from
`hyperpolymath/gossamer` `android/src/main/java/io/gossamer/`)

- `io.gossamer.GossamerActivity extends android.app.Activity`.
- Loads `libgossamer.so` via `System.loadLibrary("gossamer")` in a
static block.
- `onCreate()` builds a full-screen `WebView`, enables JS + DOM storage,
**disables** `file://`/content access, registers the `GossamerBridge` JS
interface (`window.GossamerBridge.postMessage(json)`), and calls native
`nativeInit(activity, webview)`.
- Content via overriding **`getInitialHtml()`** (HTML `String`) or
**`getInitialUrl()`** (URL `String`); `getInitialHtml()` takes
precedence — we override it.
- Gossamer on Android is **webview-only today**.
- Assumed: the gossamer Android sources + `libgossamer.so` are
vendored/linked into the app module at build time (sub-PR #8), so
`io.gossamer.GossamerActivity` is on the classpath. The shim is
therefore not part of any CI build step yet.

## TODOs / risks for sub-PRs #4#8

- **#4** — Port `NativeLib`: map the 11 JNI methods
(init/start/stop/processSensor/queryLocal/queryClaude/query/getNeuralContext/getState/reset/isRunning)
to Gossamer IPC command handlers calling the Rust core
(`crates/neurophone-core`, `crates/neurophone-android`). IPC
name/payload contract is **undefined**.
- **#5** — Port `NeurophoneService` foreground sensor loop.
- **#6** — Port `BootReceiver`.
- **#7** — Port the home-screen widgets.
- **#8** — Real frontend bundle (`frontendDist`) + full IPC wiring;
**enable `gossamer-rs`** (resolve the sibling-checkout/build-integration
question); decide `gossamer` CLI vs Gradle for the APK build; then
remove the legacy Kotlin `android/app/` tree.
- **Licensing risk**: `gossamer-rs` is `AGPL-3.0-or-later`; everything
added here is `MPL-2.0`. Whether the cdylib linking `gossamer-rs` can
stay MPL-2.0 or must adopt a compatible license is an **open question**
to resolve before #8.

Refs #83, #97, #109.

https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw)_

Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 6, 2026
## neurophone sub-PR #6 — port BootReceiver

Part of the Android Kotlin→Rust/Gossamer migration (epic #83, RFC PR
#97, sub-issue #112).

### What this does
Replaces the Kotlin `BootReceiver` with a **thin, hand-written Java**
`BroadcastReceiver` shim. On `BOOT_COMPLETED` / `LOCKED_BOOT_COMPLETED`
it starts the neurophone foreground `NeurophoneService` (the service
from sub-PR #5) via `startForegroundService`. The receiver carries **no
business logic** — any runtime policy (e.g. "was it running before
reboot?") and all inference live behind the Rust JNI
(`crates/neurophone-android`), reached through the service start path,
not here.

### Files changed
- **Added** `android/app/src/main/java/ai/neurophone/BootReceiver.java`
— Java shim, `SPDX-License-Identifier: MPL-2.0`.
- **Deleted** `android/app/src/main/java/ai/neurophone/BootReceiver.kt`.
- **Modified** `android/app/src/main/AndroidManifest.xml` — receiver
registration is class-name based (`.BootReceiver`) and therefore
migration-transparent; only updated the surrounding comment + a
`TODO(#83 rebase)` marker.

### Constraints honoured
- Hand-written Java lives **only** under `android/`, covered by the
existing `.hypatia-baseline.json` exemption (`android/**`, tracking
#97). No baseline edit needed.
- New file carries `SPDX-License-Identifier: MPL-2.0`.
- Change set is **Java + manifest only**; touches **zero** Rust files.
`android/` is not a cargo workspace member, so the Rust workspace is
unaffected.

### Verified
- No stale references: only the manifest references `.BootReceiver`
(correct, class-name based); no Kotlin/Gradle references to the removed
class remain.
- `android/` confirmed absent from the cargo `[workspace] members` list
— the migration changes cannot affect the Rust build.
- Ran `cargo build --workspace`: **pre-existing** failures in
`esn`/`lsm` (a `rand` / `ndarray-rand` trait-bound mismatch: `no method
named random/sample found for &mut impl Rng`). These reproduce on
**pristine `main` with zero changes** and are unrelated to this PR.
`cargo test --workspace` is blocked by the same pre-existing compile
failure. This PR does not introduce or worsen them.

### TODOs / risks
- `TODO(#83 rebase)` — depends on sub-PRs #3 (scaffolding), #4
(NativeLib→Rust), #5 (Service shim), none yet merged. The
`NeurophoneService` reference and package layout are assumed from
current `main`; re-point if #4/#5 rename or relocate the service
entrypoint.
- `TODO(#83)` — once the Rust JNI boot-policy entrypoint exists,
delegate the "should we restart?" decision to
`crates/neurophone-android` instead of unconditionally starting the
service.
- Risk: pre-existing `esn`/`lsm` workspace build break is environmental
(dependency drift) and should be tracked separately; it is **not**
caused by this PR.

https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw)_

Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 6, 2026
## Sub-PR #5 — Port `NeurophoneService` (Kotlin → Java JNI shim)

Part of the Android Kotlin→Rust/Gossamer migration: epic #83, RFC PR
#97, sub-issue #111.

> **Draft / depends on unmerged work.** Sub-PR #3 (Gossamer scaffolding)
and #4 (NativeLib→Rust JNI in `crates/neurophone-android`) are being
built in parallel and are **not merged**. This PR bases off `main`,
assumes their structure, and marks integration seams `TODO(#83 rebase)`.

### What changed
- **Removed**
`android/app/src/main/java/ai/neurophone/NeurophoneService.kt` (Kotlin
foreground service that carried business logic + synthetic salience +
widget publishing).
- **Added**
`android/app/src/main/java/ai/neurophone/NeurophoneService.java` — a
minimal hand-written **Java** `Service` shim. Same class name
(`ai.neurophone.NeurophoneService`), so the existing `BootReceiver.kt`,
`widget/NeurophoneAppWidget.kt`, and the `AndroidManifest.xml`
`.NeurophoneService` entry resolve to it unchanged.

### JNI calls used (`NativeLib`, Kotlin `object` → `NativeLib.INSTANCE`)
- `onCreate()` → `NativeLib.init(null)` then `NativeLib.start()`
- `onDestroy()` → `NativeLib.stop()`
- `onSensorChanged()` → `NativeLib.processSensor(typeId, values,
timestampNs, accuracy)`

All JNI calls are wrapped in `try/catch (Throwable)` so dev hardware
without the native lib still runs (matches prior Kotlin behaviour).

### Convenience mapping replicated
Sensor type → compact id (mirrors the old `NativeLib.pushSensorEvent`
table):

| sensor | id |
|---|---|
| accelerometer | 1 |
| magnetometer | 2 |
| gyroscope | 4 |
| light | 5 |
| proximity | 8 |
| (else) | 0 |

Timestamp converted **ms → ns** (`System.currentTimeMillis() *
1_000_000L`). Accuracy defaults to `3` (`SENSOR_STATUS_ACCURACY_HIGH`).

### Kept thin (in scope)
Business logic stays in Rust. The shim keeps only the Android-owned
concerns: foreground notification + channel, partial wake lock, and
sensor registration (accelerometer only for now). Widgets / boot
receiver / UI **not** ported.

### Verification
- Diff touches **only** files under `android/` (one Java add, one Kotlin
delete). No Rust or `Cargo.*` files changed → cargo behaviour is
identical to `main`.
- `cargo build --workspace` and `cargo test --workspace` **fail on
`main` already**, in `crates/lsm` and `crates/esn` only (pre-existing
rand 0.10 API drift: `random()`/`sample()` no longer resolve). This is
unrelated to this PR and unaffected by it. The `neurophone-android`
crate is an untouched stub and compiles.

### TODOs / risks
- `TODO(#83 rebase)`: `NativeLib` JNI signatures depend on sub-PR #4
landing the Rust exports (`init`/`start`/`stop`/`processSensor`).
- `TODO(#83)`: widen sensor registration beyond accelerometer once the
Rust core consumes the full set (the id mapping already covers them).
- `TODO(#83)`: foreground notification / wake lock should migrate behind
Gossamer/Rust, shrinking or removing this shim with the rest of
`android/`.
- Risk: Java↔Kotlin-`object` interop uses `NativeLib.INSTANCE`; if #4
reimplements `NativeLib` as a Java class or changes the singleton shape,
the call sites need a trivial rebase (flagged).

https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw)_

Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 6, 2026
…gacy android/ tree (#124)

## ⚠️ BLOCKED — DO NOT MERGE (gated draft)

**This is the TERMINAL, GATED step of the Android Kotlin→Rust/Gossamer
migration** (epic #83, RFC PR #97, sub-issue #115).

It is **gated on sub-PRs #3#8** (scaffolding + all component ports),
which are **NOT done**. Deleting `android/` now removes the **only
working Android frontend**, so this PR **MUST NOT be merged until #3#8
have landed**.

- Status: **DRAFT / BLOCKED**
- Merge only after: **#3, #4, #5, #6, #7, #8** are all merged
- After those land, **rebase this branch on `main`** so the diff removes
only what is truly legacy (the Kotlin/Gradle files), leaving the Java
shims + Rust + AffineScript UI delivered by #3#8 in place.

> Because #3#8 are not merged into this branch, the diff here simply
deletes the **current** `android/` tree. That is expected for this
staging draft.

---

## What was removed

The legacy Kotlin/Gradle `android/` app — **20 files**:

- **7 `*.kt`**: `BootReceiver.kt`, `MainActivity.kt`, `NativeLib.kt`,
`NeurophoneService.kt`, `widget/NeurophoneAppWidget.kt`,
`widget/NeurophoneWidgetActions.kt`,
`widget/NeurophoneWidgetConfigureActivity.kt`
- **3 `*.gradle.kts`**: `android/build.gradle.kts`,
`android/settings.gradle.kts`, `android/app/build.gradle.kts`
- Plus `gradle.properties`, `AndroidManifest.xml`, and the `res/` XML
(drawables, layouts, values, widget info).

After migration these are replaced by the Java shims under `android/` +
Rust (`crates/`) + AffineScript UI from #3#8.

## Carve-out removal (now stale)

The `android/**` banned-language carve-out existed in **three mirrored
locations**, all justified only while banned Kotlin lived in `android/`.
With the tree gone they are stale and a stale-baseline detector would
otherwise warn, so all three are removed:

1. **`.hypatia-baseline.json`** — the glob `file_pattern: "android/**"`
entry removed; file is now an empty array `[]` (it was the only entry).
*(A pure-JSON array schema cannot carry an SPDX comment without breaking
the schema the detector reads; the original file had no SPDX header
either.)*
2. **`.hypatia-ignore`** — the per-file
`cicd_rules/banned_language_file:android/...` lines removed (these
mirrored the canonical glob).
3. **`.github/workflows/language-policy.yml`** — the `android/` prune in
the *Check for Java/Kotlin files* step removed; the check is now an
unconditional scan.

## Expected end state

With the legacy tree gone and no carve-out:

- ✅ **`Check for Banned Languages`** — green, no exemption needed.
- ✅ **`governance / Language / package anti-pattern policy`** — green,
no exemption needed.

## Verification

- **Rust workspace unaffected.** The `android/` Gradle tree is **not** a
cargo member — `cargo metadata` resolves cleanly and references the
`android/` tree **0 times**. The Rust JNI crate
`crates/neurophone-android` is a separate workspace member and is
**untouched**.
- **Pre-existing build failure (NOT caused by this PR).** `cargo build
--workspace` / `cargo test --workspace` currently fail to compile in
`crates/esn` and `crates/lsm` due to a `rand`-crate API breakage
(`.random()` / `.sample()` no longer resolve under the locked `rand`
version). This failure reproduces on **pristine `main` with `android/`
still present** (verified by building `-p esn` on `origin/main`), so it
is **entirely independent** of this deletion. This PR neither introduces
nor fixes that failure and does not touch `Cargo.lock`.

## Out of scope (noted)

Narrative docs (`EXPLAINME.adoc`, `TESTING-REPORT.adoc`,
`docs/BT-PRESENCE-PLAN.adoc`) still mention the old `android/app/...`
Kotlin paths. They are non-build prose describing the legacy app and are
intentionally left for the migration-docs update accompanying #3#8;
nothing in the build/CI consumes them.

---

PART OF: epic #83 · RFC PR #97 · sub-issue #115

https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw)_

Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Jun 7, 2026
…activity (#83) (#128)

## Sub-PR #7 — port the widget triple

Part of the Android Kotlin→Rust/Gossamer migration (epic #83, RFC PR
#97, sub-issue #113).

Replaces the home-screen widget Kotlin with thin hand-written **Java**
shims that JNI into the Rust core (`crates/neurophone-android`) via
`NativeLib.getState()` / `NativeLib.query(...)`. The widget is now
**stateless**: every render reads live `salience` / `description`
straight from the Rust core instead of caching in SharedPreferences.

### Files changed
**Ported (Kotlin → Java):**
- `NeurophoneAppWidget.kt` → `NeurophoneAppWidget.java` —
`AppWidgetProvider` shim. Reads core state via `NativeLib.getState()`
(JSON, parsed defensively) and `isRunning()`; toggle/refresh/ask actions
preserved. Adds `public static requestRefresh(Context)` for non-widget
callers.
- `NeurophoneWidgetActions.kt` → `NeurophoneWidgetActions.java` —
`BroadcastReceiver` shim. The old `PUBLISH_STATE` (extras +
SharedPreferences) path is gone; receiver now does `FORCE_REFRESH`
(re-render from core) and `ACTION_QUERY` (one-shot
`NativeLib.query(...)` then refresh).

**Dropped (owner decision):**
- `NeurophoneWidgetConfigureActivity.kt` — **deleted, not ported.** It
had **no manifest `<activity>` entry**; its only registration was
`android:configure=...` in `res/xml/neurophone_widget_info.xml`, now
removed along with
`android:widgetFeatures="reconfigurable|configuration_optional"` and the
`widget_configure_*` strings. **The widget works with no configure
step.**

**Knock-on edits (Kotlin callers of the removed widget API, kept
compiling):**
- `NeurophoneService.kt` — `publishState(...)` call sites →
`requestRefresh(...)` (core is now source of truth).
- `BootReceiver.kt` — dropped the removed
`NeurophoneAppWidget.prefs/KEY_RUNNING` read (a core concern now);
conservatively no-ops on boot pending a core-persisted autostart flag.
- `AndroidManifest.xml`, `neurophone_widget_info.xml`, `strings.xml` —
configure-activity removal + explanatory comments.

### Dropped configure-activity note
`NeurophoneWidgetConfigureActivity` is intentionally **not** ported per
owner decision. No manifest registration existed to remove; the
`android:configure` hook in the widget-info XML was the sole binding and
has been removed. The single optional question it asked (`local_only`)
is left for the core/UI to own post-migration.

### What I verified
- All new Java files carry `SPDX-License-Identifier: MPL-2.0`;
hand-written Java is permitted **only under `android/`** via the
existing `.hypatia-baseline.json` `android/**` carve-out.
- No live code references any removed symbol (`publishState`, `prefs`,
`KEY_RUNNING`, `NeurophoneWidgetConfigureActivity`, `KEY_LOCAL_ONLY`) —
remaining hits are comments/docstrings only.
- All referenced widget layout IDs (`widget_state`, `widget_salience`,
`widget_salience_value`, `widget_toggle`, `widget_refresh`,
`widget_query`) exist in `widget_neurophone.xml`.
- XML well-formedness checked for the manifest, widget-info, and
strings.
- **Rust workspace:** `cargo build --workspace` / `cargo test
--workspace` currently **fail on a pre-existing breakage in `esn` and
`lsm`** (a `rand` / `ndarray-rand` API mismatch: `no method named
random/sample`, `impl Rng: ndarray_rand::rand::Rng` unsatisfied).
**Reproduced on a clean `origin/main` with all PR changes stashed**, so
it is not introduced here. This PR touches **no Rust** (android-only
diff) and does not regress the workspace. `neurophone-android` itself
only fails transitively through `esn`/`lsm`.

### TODOs / risks
- `TODO(#83 rebase)` markers flag the seams that depend on parallel
sub-PRs **#3/#4/#5** (not yet merged):
- `NativeLib` is still the pre-migration Kotlin `object`, so the Java
shims use `NativeLib.INSTANCE.…`; drop `.INSTANCE` if #3/#4/#5 republish
it as a Java facade.
- The `getState()` JSON schema (`salience`, `description` keys) is the
agreed contract but should be confirmed/tightened on rebase. JNI calls
are wrapped in `try { } catch (Throwable)` so the widget never crashes
the launcher against the current stub crate (`UnsatisfiedLinkError`).
- `BootReceiver` autostart and the service's per-tick salience push need
the core-side persisted run/state APIs from #3/#4/#5.

### Open questions
- Should the dropped configure activity's `local_only` preference be
re-surfaced somewhere (settings screen / core config), or is it gone for
good?
- Confirm the final `NativeLib` shape (Kotlin `object` vs Java facade)
so the `.INSTANCE` interop can be cleaned up on rebase.

> Marked **DRAFT**: depends on parallel sub-PRs #3/#4/#5 (base off
`main`, structure assumed, `TODO(#83 rebase)` markers).

https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw)_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant